package com.jtx.miaoah2.MQConsumer;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.jtx.miaoah2.Cache.GoodsSeckillCache;
import com.jtx.miaoah2.Cache.GoodsTokenCache;
import com.jtx.miaoah2.Common.RabbitMqConstants;
import com.jtx.miaoah2.Mapper.SkGoodsSeckillMapper;
import com.jtx.miaoah2.Mapper.SkOrderInfoMapper;
import com.jtx.miaoah2.Mapper.SkOrderMapper;
import com.jtx.miaoah2.Model.goods.DO.SkGoodsSeckill;
import com.jtx.miaoah2.Model.order.DO.SkOrder;
import com.jtx.miaoah2.Model.order.DO.SkOrderInfo;
import com.jtx.miaoah2.Model.order.DTO.CreateOrderDto;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;

/**
 * @author 季台星
 * @Date 2023 07 24 19 02
 */
@Component
@Slf4j
public class SnappedListener {

    @Autowired
    private GoodsSeckillCache goodsSeckillCache;

    @Autowired
    private SkOrderMapper skOrderMapper;

    @Autowired
    private SkOrderInfoMapper skOrderInfoMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private SkGoodsSeckillMapper skGoodsSeckillMapper;

    @Autowired
    private GoodsTokenCache goodsTokenCache;


    @Transactional(rollbackFor = Exception.class)
    @RabbitListener(queues = "snappedQueue1")
    public void getMsg(String msg, Channel channel,
                       @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag){
        System.out.println("消费者1消费消息" + msg);
        try {
            channel.basicAck(deliveryTag, false);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //创建订单，预扣库存，五分钟内用户为支付则释放库存
        CreateOrderDto createOrderDto = JSON.parseObject(msg, CreateOrderDto.class);
        //判断用户是否得到令牌
        if (goodsTokenCache.tryUserLock(createOrderDto.getUserId())) {
            //这个用户没有得到令牌不进行消费
            return;
        }
        //创建订单写入数据库中
        SkOrder skOrder = new SkOrder();
        SkOrderInfo skOrderInfo = new SkOrderInfo();
        BeanUtils.copyProperties(createOrderDto,skOrder);
        BeanUtils.copyProperties(createOrderDto,skOrderInfo);
        skOrderInfoMapper.insert(skOrderInfo);
        skOrder.setOrderInfoId(skOrderInfo.getId());
        skOrderMapper.insert(skOrder);
            //使用乐观锁去释放库存
        skGoodsSeckillMapper.decrementGoodsStock1(skOrder.getSeckillId(),skOrder.getGoodsId());
        //创建支付订单，使用死信队列,过期释放库存
        rabbitTemplate.convertAndSend(RabbitMqConstants.ORDER_EXCHANGE,
                RabbitMqConstants.ORDER_ROUTEING_KEY, JSON.toJSONString(skOrder));
    }
//    @RabbitListener(queues = "snappedQueue2")
//    public void getMsg2(String msg,Channel channel,@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag){
//        System.out.println("消费者2消费消息" + msg);
//        try {
//            channel.basicAck(deliveryTag, false);
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }
//    }

    @RabbitListener(queues = "deathOrderQueue")
    public void dealOrderTimeOut(String orderInfo, Channel channel,
                                 @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
        channel.basicAck(deliveryTag, false);
        SkOrder skOrder = JSON.parseObject(orderInfo, SkOrder.class);
        log.info("订单延迟未支付，释放内存，订单信息为" + orderInfo);
        //到数据库中查询状态
        SkOrderInfo skOrderInfoNew = skOrderInfoMapper.selectById(skOrder.getOrderInfoId());
        if (skOrderInfoNew.getStatus() == 0){
            //商品未支付，释放库存，删除订单
            skOrderMapper.deleteById(skOrder.getId());
            skOrderInfoMapper.deleteById(skOrder.getOrderInfoId());
            //使用乐观锁释放库存
            skGoodsSeckillMapper.incrementGoodsStock1(skOrder.getSeckillId(),skOrder.getGoodsId());

        }
    }
}
